package org.phantom.securityframework.api.factory;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.phantom.securityframework.api.RealmRegister;
import org.phantom.securityframework.api.exception.NoneRealmException;
import org.phantom.securityframework.api.exception.UnuniqueRealmException;
import org.springframework.stereotype.Service;

@Service
public class RealmRegisterImpl implements RealmRegister,ServiceListener{

	private Map<Long,List<Object>> managerBeans = new HashMap<Long,List<Object>>();

	@Override
	public void serviceChanged(ServiceEvent event) {
		if(event.getType() == ServiceEvent.REGISTERED){
			this.registeManagerBean(event.getServiceReference());
		}else if(event.getType() == ServiceEvent.UNREGISTERING){
			this.unRegusteManagerBean(event.getServiceReference());
		}
	}
	
	protected void registeManagerBean(ServiceReference<?> sr){
		Long key = sr.getBundle().getBundleId();
		List<Object> beans = managerBeans.get(key);
		if(beans==null){
			beans = new ArrayList<Object>();
		}
		beans.add(sr.getBundle().getBundleContext().getService(sr));
		managerBeans.put(key, beans);
	}

	protected void unRegusteManagerBean(ServiceReference<?> sr){
		Long key = sr.getBundle().getBundleId();
		List<Object> beans = managerBeans.get(key);
		beans.remove(sr.getBundle().getBundleContext().getService(sr));
	}

	@Override
	public Object getRealm(Class<?> clazz)throws UnuniqueRealmException,NoneRealmException {
		List<Object> temp = new ArrayList<Object>();
		Collection<List<Object>> collection = this.managerBeans.values();
		for (List<Object> list : collection) {
			for (Object o : list) {
				Class<?>[] interfaces = o.getClass().getInterfaces();
				for (Class<?> c : interfaces) {
					if(c.getName().equals(clazz.getName())){
						temp.add(o);
					}
				}
			}
		}
		if(temp.size()>1){
			throw new UnuniqueRealmException(clazz.getName());
		}
		if(temp.size()==0){
			throw new NoneRealmException(clazz.getName());
		}
		return temp.get(0);
	}
	@Override
	public List<Object> getRealms(Class<?> clazz){
		List<Object> temp = new ArrayList<Object>();
		Collection<List<Object>> collection = this.managerBeans.values();
		for (List<Object> list : collection) {
			for (Object o : list) {
				Class<?>[] interfaces = o.getClass().getInterfaces();
				for (Class<?> c : interfaces) {
					if(c.getName().equals(clazz.getName())){
						temp.add(o);
					}
				}
			}
		}
		return temp;
	}
}
